package cn.designpattern.agent;

import sun.misc.ProxyGenerator;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DynamicAgent {
    public static void main(String[] args) throws IOException {
        FileOutputStream fileOutputStream = null;
        try {
            PeopleInvocation peopleInvocation = new PeopleInvocation(new People());
            IPeople proxy = peopleInvocation.getProxy();
            proxy.eat("apple");

            PeopleInvocation pi = (PeopleInvocation)Proxy.getInvocationHandler(proxy);
            pi.getProxy();

            // proxy
            Class<?> proxyClass = Proxy.getProxyClass(IPeople.class.getClassLoader(), IPeople.class);
            // InvocationHandler
            IPeople o = (IPeople)proxyClass.getConstructor(InvocationHandler.class).newInstance(peopleInvocation);

            byte[] bytes = ProxyGenerator.generateProxyClass("MyPiggy", new Class[]{IPeople.class});
            fileOutputStream = new FileOutputStream("D:\\codeDemo\\utils\\src\\cn\\piggy\\agent\\MyPiggy.class");
            fileOutputStream.write(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(fileOutputStream!=null){
                fileOutputStream.close();
            }
        }
    }
}

class PeopleInvocation implements InvocationHandler {
    private final IPeople people;
    public PeopleInvocation(IPeople people) {
        this.people = people;
    }
    public IPeople getProxy(){
        return (IPeople) Proxy.newProxyInstance(people.getClass().getClassLoader(), people.getClass().getInterfaces(),this);
    }
    public void before(){
        System.out.println("before");
    }
    public void after(){
        System.out.println("after");
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object invoke = method.invoke(people, args);
        after();
        return invoke;
    }
}

interface IPeople{
    void eat(String s);
}

class People implements IPeople{
    public void eat(String s){
        System.out.println("eat "+s);
    }
}

